package com.sjb.cp.service.impl;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.ObjUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.conditions.query.LambdaQueryChainWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.sjb.cp.exception.BusinessException;
import com.sjb.cp.exception.ErrorCode;
import com.sjb.cp.exception.ThrowUtils;
import com.sjb.cp.manager.sharding.DynamicShardingManager;
import com.sjb.cp.mapper.SpaceMapper;
import com.sjb.cp.model.constant.UserConstant;
import com.sjb.cp.model.enums.SpaceLevelEnum;
import com.sjb.cp.model.enums.SpaceRoleEnum;
import com.sjb.cp.model.enums.SpaceTypeEnum;
import com.sjb.cp.model.po.Picture;
import com.sjb.cp.model.po.Space;
import com.sjb.cp.model.po.SpaceUser;
import com.sjb.cp.model.po.User;
import com.sjb.cp.model.request.picture.PictureQueryRequest;
import com.sjb.cp.model.request.space.SpaceAddRequest;
import com.sjb.cp.model.request.space.SpaceQueryRequest;
import com.sjb.cp.model.vo.SpaceVO;
import com.sjb.cp.service.SpaceService;
import com.sjb.cp.service.SpaceUserService;
import com.sjb.cp.service.UserService;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.support.TransactionTemplate;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.util.Date;
import java.util.List;
import java.util.Optional;

/**
 * @Author:sjb
 * @CreateTime:2025-01-26
 * @Description: 空间基础服务实现类
 * @Version：1.0
 */
@Service
public class SpaceServiceImpl extends ServiceImpl<SpaceMapper, Space>
        implements SpaceService {

    @Resource
    private UserService userService;

    @Resource
    private TransactionTemplate transactionTemplate;

    @Resource
    private SpaceUserService spaceUserService;

    @Resource
    private DynamicShardingManager dynamicShardingManager;

    /**
     * 创建/编辑时校验
     *
     * @param add
     * @param space
     */
    @Override
    public void validateSpace(boolean add, Space space) {
        ThrowUtils.throwIf(space == null, ErrorCode.PARAMS_ERROR);
        String spaceName = space.getSpaceName();
        Integer spaceLevel = space.getSpaceLevel();
        Integer spaceType = space.getSpaceType();
        SpaceLevelEnum spaceLevelEnum = SpaceLevelEnum.getSpaceLevelEnumByValue(spaceLevel);
        SpaceTypeEnum typeEnumByValue = SpaceTypeEnum.getTypeEnumByValue(spaceType);

        if (add) {
            if (spaceName == null) {
                throw new BusinessException(ErrorCode.PARAMS_ERROR, "空间名称不能为空");
            }
            if (typeEnumByValue == null) {
                throw new BusinessException(ErrorCode.PARAMS_ERROR, "空间类型不能为空");
            }
        }

        // 编辑时校验
        if (spaceLevelEnum == null) {
            throw new BusinessException(ErrorCode.PARAMS_ERROR, "空间级别不存在");
        }
        if (StrUtil.isNotBlank(spaceName) && spaceName.length() > 30) {
            throw new BusinessException(ErrorCode.PARAMS_ERROR, "空间名称过长");
        }
    }


    @Override
    public void fillSpaceBySpaceLevel(Space space) {
        Integer spaceLevel = space.getSpaceLevel();
        SpaceLevelEnum spaceLevelEnumByValue = SpaceLevelEnum.getSpaceLevelEnumByValue(spaceLevel);
        if (spaceLevelEnumByValue != null) {
            long maxSize = spaceLevelEnumByValue.getMaxSize();
            if (space.getMaxSize() == null) {
                space.setMaxSize(maxSize);
            }
            long maxCount = spaceLevelEnumByValue.getMaxCount();
            if (space.getMaxCount() == null) {
                space.setMaxCount(maxCount);
            }
        }
    }

    @Override
    public long addSpace(SpaceAddRequest spaceAddRequest, User loginUser) {
        ThrowUtils.throwIf(spaceAddRequest == null, ErrorCode.PARAMS_ERROR);
        //填充参数默认值
        Space space = new Space();
        BeanUtils.copyProperties(spaceAddRequest, space);
        // 默认值
        if (StrUtil.isBlank(spaceAddRequest.getSpaceName())) {
            space.setSpaceName("默认空间");
        }
        if (spaceAddRequest.getSpaceLevel() == null) {
            spaceAddRequest.setSpaceLevel(SpaceLevelEnum.COMMON.getValue());
        }
        if (spaceAddRequest.getSpaceType() == null) {
            spaceAddRequest.setSpaceType(SpaceTypeEnum.PRIVATE.getValue());
        }

        // 填充属性
        this.fillSpaceBySpaceLevel(space);
        //校验参数
        this.validateSpace(true, space);
        Long userId = loginUser.getId();
        space.setId(userId);
        //校验权限，非管理员只能创建普通级别的空间
        if (SpaceLevelEnum.COMMON.getValue() != spaceAddRequest.getSpaceLevel() && !userService.isAdmin(loginUser)) {
            throw new BusinessException(ErrorCode.NO_AUTH_ERROR, "无权限创建指定级别的空间");
        }
        //控制同一用户只能创建一个私有空间 针对用户进行加锁
        String lock = String.valueOf(userId).intern();
        synchronized (lock) {
            transactionTemplate.execute(status -> {
                // 校验是否存在
                boolean exists = this.lambdaQuery()
                        .eq(Space::getUserId, userId)
                        .eq(Space::getSpaceType, spaceAddRequest.getSpaceType())
                        .exists();
                ThrowUtils.throwIf(exists, ErrorCode.OPERATION_ERROR, "每个用户每类空间只能创造一个");
                boolean saved = this.save(space);
                ThrowUtils.throwIf(!saved, ErrorCode.OPERATION_ERROR);
                // 如果是团队成员空间
                if (SpaceTypeEnum.TEAM.getValue() == spaceAddRequest.getSpaceType()) {
                    SpaceUser spaceUser = new SpaceUser();
                    spaceUser.setSpaceRole(SpaceRoleEnum.ADMIN.getValue());
                    spaceUser.setUserId(userId);
                    spaceUser.setSpaceId(space.getId());
                    boolean result = spaceUserService.save(spaceUser);
                    ThrowUtils.throwIf(!result, ErrorCode.OPERATION_ERROR);
                }
                // 创建分表
                dynamicShardingManager.createSpacePictureTable(space);
                return space.getId();
            });
        }
        return Optional.ofNullable(space.getId()).orElse(-1L);
    }


    @Override
    public QueryWrapper<Space> getQueryWrapper(SpaceQueryRequest spaceQueryRequest) {
        QueryWrapper<Space> queryWrapper = new QueryWrapper<>();
        if (spaceQueryRequest == null) {
            return queryWrapper;
        }
        // 从对象中取值
        Long id = spaceQueryRequest.getId();
        String spaceName = spaceQueryRequest.getSpaceName();
        Integer spaceType = spaceQueryRequest.getSpaceType();
        Integer spaceLevel = spaceQueryRequest.getSpaceLevel();
        Long userId = spaceQueryRequest.getUserId();

        queryWrapper.eq(ObjUtil.isNotEmpty(id), "id", id);
        queryWrapper.eq(ObjUtil.isNotEmpty(userId), "userId", userId);
        queryWrapper.eq(StrUtil.isNotBlank(spaceName), "name", spaceName);
        queryWrapper.eq(ObjectUtil.isNotEmpty(spaceType), "spaceType", spaceType);
        queryWrapper.eq(ObjectUtil.isNotEmpty(spaceLevel), "spaceLevel", spaceLevel);

        return queryWrapper;
    }

    @Override
    public SpaceVO getSpaceVo(Space space, HttpServletRequest request) {
        User loginUser = userService.getLoginUser(request);
        if (loginUser == null) {
            throw new BusinessException(ErrorCode.NO_AUTH_ERROR,"用户未登录");
        }
        SpaceVO spaceVO = new SpaceVO();
        BeanUtils.copyProperties(space,spaceVO);
        return spaceVO;
    }
}
